package com.demo.svc;

import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.ObjectInputStream;
import java.io.ObjectOutputStream;
import java.security.KeyPair;
import java.security.KeyPairGenerator;
import java.security.interfaces.RSAPrivateKey;
import java.security.interfaces.RSAPublicKey;

import javax.annotation.PostConstruct;
import javax.crypto.Cipher;

import org.apache.commons.lang3.ArrayUtils;
import org.apache.log4j.Logger;
import org.springframework.stereotype.Service;



@Service("encrytFunc")
public class Encryption {
	
	private static final int ENCRYPTIONBUFFER = 102;
	private static final int DECRYPTIONBUFFER = 128;
	
	private static final String PUBLICKEY = "Key_Rsa_Pub.dat";
	private static final String PRIVATEKEY = "Key_Rsa_Pri.dat";
	
	private RSAPublicKey   pbkey;   //public key  
	private RSAPrivateKey  prkey;  //private key
	
	private static Logger logger = Logger.getLogger(Encryption.class);
	
	
//	pbkey.getModulus()          //n(1)
//	pbkey.getPublicExponent()   //e
//	prkey.getModulus()          //n(2) n1==n2
//	prkey.getPrivateExponent()  //d
	
	@PostConstruct
	public void init()throws Exception{
		generateKey();
	}
	
	
	//生成密钥
	public void generateKey()throws Exception{
		
		//创建密钥对生成器，指定加密和解密算法为RSA
        KeyPairGenerator kpg=KeyPairGenerator.getInstance("RSA");
        
        //指定密钥的长度，初始化密钥对生成器
        kpg.initialize(1024);
        
        //生成密钥对
        KeyPair kp=kpg.genKeyPair();    
        
        //获取公钥
        pbkey=(RSAPublicKey )kp.getPublic();
        
        //获取私钥
        prkey=(RSAPrivateKey)kp.getPrivate();
        
        
       //保存公钥到文件
        ObjectOutputStream objectPbkey=new ObjectOutputStream(new FileOutputStream(PUBLICKEY));
        objectPbkey.writeObject(pbkey);
     
        //保存私钥到文件
        ObjectOutputStream objectPrkey=new ObjectOutputStream(new FileOutputStream(PRIVATEKEY));
        objectPrkey.writeObject(prkey);
        
        objectPbkey.close();
        objectPrkey.close();
        
	}
	
	
	//获取私钥n(2)，以hex16进制返回
	public String getKeyN(){
		
		byte[] bytes = prkey.getModulus().toByteArray();
		String hv;
		
		 StringBuilder stringBuilder = new StringBuilder("");
		 
		 for (int i = 0; i < bytes.length; i++) {  
	           int v = bytes[i] & 0xFF;  
	           hv = Integer.toHexString(v);  
	           if (hv.length() < 2) {  
	               stringBuilder.append(0);  
	           }  
	           stringBuilder.append(hv);
	       }  
	       return stringBuilder.toString(); 
	}
	
	
	//获取私钥d，以hex16进制返回
	public String getKeyE(){
		
		byte[] bytes = pbkey.getPublicExponent().toByteArray();
		String hv;
		
		 StringBuilder stringBuilder = new StringBuilder("");
		 
		 for (int i = 0; i < bytes.length; i++) {  
	           int v = bytes[i] & 0xFF;  
	           hv = Integer.toHexString(v);  
	           if (hv.length() < 2) {  
	               stringBuilder.append(0);  
	           }  
	           stringBuilder.append(hv);
	       }  
	       return stringBuilder.toString(); 
	}
	
	
	
	//获取公钥e，以hex16进制返回
	public String getKeyD(){
		
		byte[] bytes = prkey.getPrivateExponent().toByteArray();
		String hv;
		
		 StringBuilder stringBuilder = new StringBuilder("");
		 
		 for (int i = 0; i < bytes.length; i++) {  
	           int v = bytes[i] & 0xFF;  
	           hv = Integer.toHexString(v);  
	           if (hv.length() < 2) {  
	               stringBuilder.append(0);  
	           }  
	           stringBuilder.append(hv);
	       }  
	       return stringBuilder.toString(); 
	}
	
	
	
	//加密,返回byte[]
	public byte[] encryptionByte(String content)throws Exception{
		
		//从文件中读取公钥
        ObjectInputStream objectPukey=new ObjectInputStream(new FileInputStream(PUBLICKEY));
        RSAPublicKey pbk=(RSAPublicKey)objectPukey.readObject();
        objectPukey.close();
		
        Cipher cipher = Cipher.getInstance("RSA");
        cipher.init(Cipher.ENCRYPT_MODE, pbk);
        
        byte[] contBytes = content.getBytes("UTF-8");
        
        byte[] resBytes = new byte[]{};
        
        for(int i=0; i<contBytes.length; i += ENCRYPTIONBUFFER){
        	
        	resBytes = ArrayUtils.addAll(resBytes, cipher.doFinal(ArrayUtils.subarray(contBytes,i,i+ENCRYPTIONBUFFER)));
        }
        
        return resBytes;
        
	}
	
	
	//加密,返回hex16进制string
	public String encryptionHex(String content)throws Exception{
		
		//从文件中读取公钥
        ObjectInputStream objectPukey=new ObjectInputStream(new FileInputStream(PUBLICKEY));
        RSAPublicKey pbk=(RSAPublicKey)objectPukey.readObject();
        objectPukey.close();
		
        Cipher cipher = Cipher.getInstance("RSA");
        cipher.init(Cipher.ENCRYPT_MODE, pbk);
        
        byte[] contBytes = content.getBytes("UTF-8");
        
        byte[] resBytes = new byte[]{};
        
        for(int i=0; i<contBytes.length; i += ENCRYPTIONBUFFER){
        	
        	resBytes = ArrayUtils.addAll(resBytes, cipher.doFinal(ArrayUtils.subarray(contBytes,i,i+ENCRYPTIONBUFFER)));
        }
        
        String hv;
		
		StringBuilder stringBuilder = new StringBuilder("");
		 
		for (int i = 0; i < resBytes.length; i++) {  
	          int v = resBytes[i] & 0xFF;  
	          hv = Integer.toHexString(v);  
	          if (hv.length() < 2) {  
	              stringBuilder.append(0);  
	          }  
	          stringBuilder.append(hv);
	    }  
	    return stringBuilder.toString(); 
        
	}
	
	
	
	
	//解密,返回byte[]
	public byte[] decryptionByte(byte[] content)throws Exception{
		
		//读取密文
        //BigInteger c=new BigInteger(content); //没有用到
        
        //获取私钥 
        ObjectInputStream objectPrkey = new ObjectInputStream(new FileInputStream(PRIVATEKEY));
        RSAPrivateKey prk =(RSAPrivateKey)objectPrkey.readObject();
        objectPrkey.close();
        
        Cipher cipher = Cipher.getInstance("RSA");
        cipher.init(Cipher.DECRYPT_MODE, prk);
        
        byte[] resBytes = new byte[]{};
        
        for(int i=0; i<content.length; i += DECRYPTIONBUFFER){
        	resBytes = ArrayUtils.addAll(resBytes,cipher.doFinal(ArrayUtils.subarray(content,i,i+DECRYPTIONBUFFER)));
        }
        
        String res = new String(resBytes,0,resBytes.length,"UTF-8");
        
        logger.debug("解密密文："+res);
        
        
        return resBytes;
        
	}
	
	
}
